package com.lvtu.monitor.quartz;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.lvmama.com.lvtu.common.utils.JedisTemplate;
import com.lvtu.monitor.dao.exmatch.po.ExJobPattern;
import com.lvtu.monitor.module.web.module.po.IndexException;
import com.lvtu.monitor.mongo.service.IBaseMongoService;
import com.lvtu.monitor.utils.Constants;
import com.lvtu.monitor.utils.ElasticUtils;
import com.lvtu.monitor.utils.mail.SimpleMailSender;

/**
 * @Title: ExceptionAlertJob.java
 * @Package com.lvtu.monitor.quartz
 * @Description: 项目异常定时报警任务
 * @author dengcheng
 * @date 2015-5-26 下午1:55:13
 * @version V1.0.0
 */
@Component
public class ExceptionAlertJob {

	private static Logger log = Logger.getLogger(ExceptionAlertJob.class);

	private final String KEY_LAST_EXEC_TIME = "lvtu_monitor_job_exec_time";

	@Autowired
	IBaseMongoService mongoService;

	public void run(JobExecutionContext context) {
		log.info("★★★★★★★★★★★" + "ExceptionAlertJob is running" + "★★★★★★★★★★★");

		// TODO
		// 1. 从mongo中查询所有的报警规则
		List<ExJobPattern> jobPatterns = mongoService
				.findAll(ExJobPattern.class);
		if (CollectionUtils.isEmpty(jobPatterns)) {
			log.info("no exception alert job...");
			return;
		}

		// 2. 从elastic索引中查找从上次任务到现在的异常信息
		Long fromTime = this.getLastReportTime();
		Long endTime = System.currentTimeMillis();
		log.info("query exception index from elastic...between [" + fromTime
				+ "] to [" + endTime + "]");

		FilterBuilder filter = FilterBuilders.rangeFilter("createdTime")
				.gt(fromTime).lt(endTime);
		SortBuilder sort = SortBuilders.fieldSort("createdTime").order(
				SortOrder.DESC);

		List<IndexException> indexExceptions = ElasticUtils.getInstance()
				.queryIndex(Constants.ELASTIC_INDEX_EX_TRACE,
						IndexException.class, null, filter, sort, 0,
						Integer.MAX_VALUE);

		// 3. 判断异常信息是否匹配报警规则
		Map<String, String> emailContentMap = new HashMap<String, String>();
		for (IndexException indexException : indexExceptions) {
			String exMsg = indexException.toString();
			for (ExJobPattern jobPattern : jobPatterns) {
				Pattern regex = Pattern.compile(jobPattern.getPattern());
				Matcher matcher = regex.matcher(exMsg);
				if (!matcher.find()) {
					continue;
				}
				String content = this.generateEmailBody(indexException);

				String existContent = emailContentMap.get(jobPattern.get_id());
				if (existContent != null) {
					emailContentMap.put(jobPattern.get_id(), existContent
							+ content);
				} else {
					emailContentMap.put(jobPattern.get_id(), content);
				}
			}
		}

		// 4. 给规则中定义的邮箱发送邮件
		for (ExJobPattern jobPattern : jobPatterns) {
			String exMsgContent = emailContentMap.get(jobPattern.get_id());
			if (StringUtils.isEmpty(exMsgContent)) {
				continue;
			}

			String emails = jobPattern.getEmail();
			if (StringUtils.isEmpty(emails)) {
				continue;
			}
			for (String email : emails.split(",")) {
				log.info(jobPattern.getPatternName() + ",send mail to " + email);
				SimpleMailSender.sendHtmlMail(email, exMsgContent,
						jobPattern.getPatternName());
			}
		}
		this.saveReportTime(endTime);
	}

	/**
	 * 获取上次发送异常报告的时间
	 * 
	 * @return
	 */
	private Long getLastReportTime() {
		JedisTemplate reader = JedisTemplate.getReaderInstance();
		String lastTimeStr = reader.get(KEY_LAST_EXEC_TIME);
		if (StringUtils.isEmpty(lastTimeStr)
				|| !StringUtils.isNumeric(lastTimeStr)) {
			return 0L;
		}
		return Long.valueOf(lastTimeStr);
	}

	/**
	 * 保存发送异常报告的时间
	 * 
	 * @param endTime
	 */
	private void saveReportTime(Long endTime) {
		JedisTemplate writer = JedisTemplate.getWriterInstance();
		writer.set(KEY_LAST_EXEC_TIME, endTime.toString());
	}

	/**
	 * 给报错信息对象生成Email正文
	 * 
	 * @param indexException
	 * @return
	 */
	private String generateEmailBody(IndexException ex) {
		StringBuilder content = new StringBuilder();
		content.append("Time:").append(ex.getCreatedTimeStr()).append("\r\n");
		content.append("Msg:").append(ex.getException());
		return content.toString();
	}

}
